package com.visec.hdy.hadoop.fsb;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

import org.apache.log4j.Logger;

import com.visec.hdy.hadoop.standard.FSB;

/**
 * 依赖文件系统实现存储实现类
 * 
 * @author hdy
 *
 */
public class FileSystemFSB implements FSB {

	Logger l = Logger.getLogger(FileSystemFSB.class);

	protected void createFloder(File file) {
		if (!file.getParentFile().exists())
			file.getParentFile().mkdirs();
	}

	@Override
	public void create(File file, InputStream inputStream) {
		createFloder(file);
		try (FileOutputStream fileOutput = new FileOutputStream(file); InputStream i = inputStream) {
			copyStream(fileOutput, i);
		} catch (IOException e) {
			l.error("", e);
		}
	}

	protected void copyStream(OutputStream o, InputStream i) throws IOException {
		byte[] b = new byte[2048];
		int a = i.read(b);
		while (a > 0) {
			o.write(b, 0, a);
			a = i.read(b);
		}
	}

	@Override
	public OutputStream create(File file) {
		try {
			createFloder(file);
			return new FileOutputStream(file);
		} catch (FileNotFoundException e) {
			l.error("", e);
		}
		return null;
	}

	@Override
	public void append(File file, InputStream inputStream) {
		createFloder(file);
		try (FileOutputStream fileOutput = new FileOutputStream(file, true); InputStream i = inputStream) {
			copyStream(fileOutput, i);
		} catch (IOException e) {
			l.error("", e);
		}
	}

	@Override
	public OutputStream append(File file) {
		try {
			createFloder(file);
			return new FileOutputStream(file, true);
		} catch (FileNotFoundException e) {
			l.error("", e);
		}
		return null;
	}

	@Override
	public boolean delete(File file, boolean isRecursion) {
		if (!file.exists())
			return true;
		try {
			if (!isRecursion)
				return Files.deleteIfExists(file.toPath());
			if (file.isDirectory())
				for (File f : file.listFiles())
					delete(f, isRecursion);
			return Files.deleteIfExists(file.toPath());
		} catch (IOException e) {
			l.error("", e);
		}
		return false;
	}

	@Override
	public InputStream get(File file) {
		try {
			return new FileInputStream(file);
		} catch (FileNotFoundException e) {
			l.error("", e);
		}
		return null;
	}

	@Override
	public boolean isExist(File file) {
		return file.exists();
	}

	@Override
	public List<File> listFiles(File file) {
		return list(File::isFile, file);
	}

	protected List<File> list(Predicate<File> predicate, File file) {
		if (!file.exists())
			file.mkdirs();
		File[] listFiles = file.listFiles();
		List<File> li = new ArrayList<>();
		for (File f : listFiles) {
			if (predicate.test(f))
				li.add(f);
		}
		return li;
	}

	@Override
	public List<File> listDirs(File file) {
		return list(File::isDirectory, file);
	}

	@Override
	public void close() {
		return;
	}

	@Override
	public List<File> listAll(File file) {
		return list(a -> true, file);
	}

}
